package skewreduce.lib;

import java.util.Collection;
import java.util.Iterator;

import skewreduce.dfof.InternalParticle;


public class NodeList<E extends KDTreeNode> implements Iterable<E> {

    private int numElem;
    private E head;
    private E tail;

    public NodeList() {}

    public void add(E e) {
        if ( tail == null ) {
            head = tail = e;
            e.setLeft(null);
            e.setRight(null);
        } else {
            e.setLeft(tail);
            e.setRight(null);
            tail.setRight(e);
            tail = e;
        }
        ++numElem;
    }

    public void addAll(Collection<? extends E> c) {
        for ( E e : c ) add(e);
    }

    public int size() { return numElem; }
    public void clear() {
        numElem = 0;
        head = null; tail = null;
    }

    public <T extends KDTreeNode> T[] toArray(T[] a) {
        T[] r = a.length >= numElem ? a :
            (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), numElem);
        E cursor = head;
        for ( int i = 0; i < r.length; ++i ) {
            r[i] = (T)cursor;
            cursor = (E)cursor.getRight();
        }
        return r;
    }

    public Iterator<E> iterator() {
        return new Iterator<E>() {
            E cursor = head;

            public boolean hasNext() { return cursor != null; }
            public E next() {
                E v = cursor;
                cursor = (E)cursor.getRight();
                return v;
            }
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

    public static void main(String[] args) {
        NodeList<InternalParticle> p = new NodeList<InternalParticle>();
        java.util.Random r = new java.util.Random();
        /*
        for ( int i = 0; i < 10; ++i ) {
            InternalParticle y = new InternalParticle(i,r);
            System.out.println(y);
            p.add(y);
        }

        InternalParticle[] x = new InternalParticle[p.size()];
        p.toArray(x);

        System.out.println("AFTER");

        for ( InternalParticle q : x )
            System.out.println(q);
            */
        int i = 0;
        try {
            while ( true ) {
                p.add(new InternalParticle(++i,r));
            }
        } catch ( OutOfMemoryError ignore ) {
        } finally {
            p.clear();
            System.gc();
            System.out.println("SIZE = "+i);
        }

        java.util.ArrayList<InternalParticle> l = new java.util.ArrayList<InternalParticle>();

        i = 0;
        try {
            while ( true ) {
                l.add(new InternalParticle(++i,r));
            }
        } catch ( OutOfMemoryError ignore ) {
        } finally {
            l.clear();
            System.gc();
            System.out.println("SIZE = "+i);
        }
    }
}
